import {
  IPublicEnumTransformStage,
  IPublicTypeConfigure,
  IPublicTypeFieldConfig,
  IPublicTypeProjectSchema,
  IPublicTypeRootSchema,
} from '@alilc/lowcode-types';
import { parseTsType } from '../../../code-transformer/utils/export/parseTsType';
import { dataTypeToSchema } from '../../..//utils/dataTypeToSchema';
import { ITypeEntity } from '../../../../../../modules/superType/types';
import { actionTypeToSchema } from '../../../utils/actionTypeToSchema';
import { createEmptyDocument } from '../../../../../../modules/editor/server/utils/document';
import { parseDocumentMetaFromJSX, applyMetaToDocument } from '../../utils/parseDocumentMeta';
import { LcDocument } from '../../../../../../modules/editor/types/editor.type';
import { TSXComplianceChecker } from '../../services/TSXComplianceChecker';
import { getFileInfoFromPath } from '../../utils/getFileInfoFromPath';
import { codeToSchema } from '../../../code-transformer/codeToSchema';
import { transformJS } from '../../../code-transformer/utils/transform';
import { defaultBabelConfig } from '../../../code-transformer/config/default-babel-config';
import { sampleTypeFromDefault } from '../../../../../../modules/superType/utils/sampleTypeField';
import {
  getCurrentProject,
  getDocument,
  loadComponent,
  loadSourceDoc,
} from '../../../../../../../utils/editor-adapter/editorResource';
import { parsingCss } from '../css-transform/parsingCss';

export const validateAndUpdateDocumentCss = async (
  fileName: string,
  content: any,
  schema: IPublicTypeRootSchema,
) => {
  const cssList = parsingCss(content, {
    existCssList: (schema as any)?.cssList || [],
  });
  const updatedSchema = {
    ...schema,
    fileName,
    css: content,
    cssList,
  };
  return updatedSchema;
};

export const validateAndUpdateDocument = async (
  projectId: string,
  path: string,
  content: any,
  options?: {
    schema?: IPublicTypeRootSchema;
    existDocument?: LcDocument;
  },
): Promise<{ complianceResult?: any; doc?: LcDocument }> => {
  // console.log('validateAndUpdateDocument: ', path, content);
  const { schema: rootSchema, existDocument } = options || {};

  // TSX 规范检查
  if (path.endsWith('.tsx')) {
    const complianceResult = TSXComplianceChecker.checkTSXCompliance(content, path);

    // 统一的错误处理：始终返回结果而不是抛出异常
    if (!complianceResult.isCompliant) {
      const errors = complianceResult.issues.filter((issue) => issue.type === 'error');
      const report = TSXComplianceChecker.generateReport(complianceResult, path);
      console.warn('TSX 规范检查失败:', report);

      // 返回统一的错误结果格式
      return {
        complianceResult: {
          ...complianceResult,
          report,
          errors: errors, // 明确的错误数组
        },
      };
    }
  }

  const { name: fileName, desc, folder } = getFileInfoFromPath(path, content);

  // 解析 JSX 文件头部的元数据注释
  const parsedMeta = parseDocumentMetaFromJSX(content);
  console.log('parsedMeta: ', parsedMeta);

  const documentCodeIndex = content.search(
    /class\s+(\w+)\s+extends\s+(React\.)?Component(\s*<[^>]+>)?/,
  );
  let doc =
    typeof existDocument === 'undefined' || existDocument
      ? existDocument
      : await getDocument(fileName);
  let isNew = false;
  if (!doc) {
    // 创建新文档时，优先使用解析出的元数据
    doc = createEmptyDocument({
      type: parsedMeta.type || 'Page',
      fileName,
      title: parsedMeta.title || desc || fileName,
      folder: folder || undefined,
    });
    // 应用解析出的其他元数据（新文档允许覆盖）
    doc = applyMetaToDocument(doc, parsedMeta, 'overwrite') as LcDocument;
    isNew = true;
  } else {
    // 更新现有文档时，使用智能合并策略
    doc = applyMetaToDocument(doc, parsedMeta, 'overwrite') as LcDocument;
  }

  const { schema, methods, usedComponentNames, properties, defaultProps } =
    await codeToSchema.transform(content.slice(documentCodeIndex), {
      reactNodeProps: ['children'],
    });
  // 判断未加载的自定义组件
  const allCustomComponentNames = (await getCurrentProject(projectId)).documents
    .filter((_) => _.type === 'Component')
    .map((_) => _.fileName);

  let unPullSourceFileNames = new Set<string>();
  for (const componentName of usedComponentNames) {
    if (allCustomComponentNames.includes(componentName)) {
      const doc = await getDocument(componentName);
      if (!doc?.schema) {
        unPullSourceFileNames.add(componentName);
      }
    }
  }
  if (unPullSourceFileNames.size > 0) {
    await loadSourceDoc(Array.from(unPullSourceFileNames));
    await loadComponent(Array.from(unPullSourceFileNames));
  }
  console.log('unPullSourceFileNames: ', unPullSourceFileNames);
  console.log('usedComponentNames: ', usedComponentNames);
  // console.log(JSON.parse(JSON.stringify(schema.state)));
  console.log('schema: ', schema);
  console.log('methods: ', methods);
  const newTypes: ITypeEntity[] = [];

  if (schema.componentName === 'React.Fragment') {
    schema.componentName = 'Component';
  }

  if (doc.type === 'Page') {
    if (schema.componentName !== 'Page') {
      schema.componentName = 'Page';
    }
  } else if (doc.type === 'Component') {
    if (schema.componentName !== 'Component') {
      const { componentName, condition, loop, loopArgs, props, children, title } = schema;
      schema.componentName = 'Component';
      delete schema.props;
      delete schema.loop;
      delete schema.loopArgs;
      delete schema.children;
      delete schema.title;
      schema.children = [
        {
          componentName,
          props,
          condition,
          loop,
          loopArgs,
          children,
          title,
        },
      ];
    }
  } else {
  }

  let headerContent = content.slice(0, documentCodeIndex);

  if (headerContent.includes('interface IState')) {
    headerContent = headerContent.replace('interface IState', 'class IState');
  }

  if (headerContent.includes('interface IProps')) {
    headerContent = headerContent.replace('interface IProps', 'class IProps');
  }

  // 解析 IState 类（数据类型）
  console.log('开始解析 IState，headerContent 长度:', headerContent.length);
  console.log('headerContent 是否包含 IState:', headerContent.includes('class IState'));

  let dataType: ITypeEntity;
  try {
    let parsedDataType = await parseTsType(headerContent, 'object', 'IState');
    console.log('parseTsType 返回结果类型:', typeof parsedDataType);
    console.log('parseTsType 返回结果:', parsedDataType);

    if (
      !parsedDataType ||
      (typeof parsedDataType === 'object' && Object.keys(parsedDataType).length === 0)
    ) {
      console.warn('parseTsType 返回空结果，尝试不指定类名解析');
      parsedDataType = await parseTsType(headerContent, 'object');
      console.log('不指定类名的解析结果:', parsedDataType);
    }

    // 如果仍然解析失败，尝试手动创建基本的 dataType 结构
    if (
      !parsedDataType ||
      (typeof parsedDataType === 'object' && Object.keys(parsedDataType).length === 0)
    ) {
      console.warn('所有解析方法都失败，尝试手动创建基本结构');
      dataType = {
        name: 'IState',
        desc: 'data',
        type: 'data',
        fields: [],
      } as ITypeEntity;

      // 尝试从代码中提取基本的字段信息
      const fieldMatches = headerContent.match(/\/\*[^*]*\*\/\s*(\w+)\?\s*:\s*([^;]+);/g);
      if (fieldMatches) {
        console.log('找到字段匹配:', fieldMatches.length);
        if (!dataType.fields) {
          dataType.fields = [];
        }
        fieldMatches.forEach((match) => {
          const fieldMatch = match.match(/\/\*\s*([^*]*)\s*\*\/\s*(\w+)\?\s*:\s*([^;]+);/);
          if (fieldMatch) {
            const [, desc, name, typeStr] = fieldMatch;
            if (dataType.fields) {
              dataType.fields.push({
                name: name.trim(),
                desc: desc.trim(),
                type: typeStr.includes('string')
                  ? 'string'
                  : typeStr.includes('number')
                  ? 'number'
                  : typeStr.includes('boolean')
                  ? 'boolean'
                  : 'object',
                required: false,
                isArray: typeStr.includes('[]'),
                isApi: false,
              });
            }
          }
        });
        console.log('手动提取的字段数量:', dataType.fields.length);
      }
    } else {
      dataType = (parsedDataType as ITypeEntity) || ({} as ITypeEntity);
    }

    console.log('最终 dataType (IState): ', JSON.parse(JSON.stringify(dataType)));
  } catch (error) {
    console.error('解析 IState 时发生错误:', error);
    dataType = {
      name: 'IState',
      desc: 'data',
      type: 'data',
      fields: [],
    } as ITypeEntity;
    console.log('使用空对象作为 dataType');
  }

  // 解析 IProps 类（属性类型）
  let propsType: ITypeEntity | undefined;
  if (headerContent.includes('IProps')) {
    propsType = (await parseTsType(headerContent, 'object', 'IProps')) as ITypeEntity;
    console.log('propsType (IProps): ', JSON.parse(JSON.stringify(propsType)));
  }
  if (typeof dataType === 'string')
    return {
      complianceResult: {
        isComplant: false,
        errors: [],
      },
    };
  if (dataType) {
    dataType.type = 'data';
    dataType.desc = 'data';
    dataType.name = 'data';
    dataType.fileName = fileName;
    // 新逻辑：以 state 为主合并 fields
    const state = (schema as IPublicTypeRootSchema).state || {};
    console.log('state: ', JSON.parse(JSON.stringify(state)));
    const fields = dataType.fields || [];
    const fieldsMap = new Map(fields.map((f: any) => [f.name, f]));
    const mergedFields: any[] = [];
    // 1. 遍历 state，优先用 state 的值
    for (const [name, value] of Object.entries(state)) {
      let field = fieldsMap.get(name) || { name };

      // 如果 dataType 中没有默认值，但 state 中有值，使用 state 的值作为默认值
      // 但保持 dataType 中已定义的类型
      // 检查是否需要更新默认值：未定义、空字符串、空数组、空对象
      const shouldUpdateDefault =
        typeof field.default === 'undefined' ||
        field.default === '' ||
        (Array.isArray(field.default) && field.default.length === 0) ||
        (typeof field.default === 'object' &&
          field.default !== null &&
          Object.keys(field.default).length === 0);

      if (shouldUpdateDefault) {
        field.default = value;

        // 只有当 dataType 中没有明确类型定义时，才根据 state 值推断类型
        if (!field.type) {
          if (typeof value === 'string') {
            field.type = 'string';
          } else if (typeof value === 'number') {
            field.type = 'number';
          } else if (typeof value === 'boolean') {
            field.type = 'boolean';
          } else if (Array.isArray(value)) {
            field.type =
              typeof value[0] === 'string'
                ? 'string'
                : typeof value[0] === 'number'
                ? 'number'
                : 'object';
            field.isArray = true;
            field.default = JSON.stringify(value, undefined, 2);
          } else if (typeof value === 'object' && value !== null) {
            field.type = 'object';
            field.default = JSON.stringify(value, undefined, 2);
          }
        } else {
          // 如果 dataType 中已有类型定义，需要根据类型格式化默认值
          if (field.type === 'object' && typeof value === 'object' && value !== null) {
            field.default = JSON.stringify(value, undefined, 2);
          } else if (field.isArray && Array.isArray(value)) {
            field.default = JSON.stringify(value, undefined, 2);
          }
          // 其他情况保持原值
        }
      }

      // 处理嵌套字段的默认值合并
      if (
        field.type === 'object' &&
        field.fields &&
        field.fields.length > 0 &&
        typeof value === 'object' &&
        value !== null
      ) {
        if (field.isArray && Array.isArray(value) && value.length > 0) {
          // 处理数组类型的嵌套字段，使用第一个元素作为默认值参考
          const firstItem = value[0];
          if (typeof firstItem === 'object' && firstItem !== null) {
            field.fields.forEach((subField: any) => {
              if (
                firstItem.hasOwnProperty(subField.name) &&
                (typeof subField.default === 'undefined' || subField.default === '')
              ) {
                subField.default = firstItem[subField.name];
                console.log(
                  `设置数组嵌套字段默认值: ${field.name}[].${subField.name} = ${subField.default}`,
                );
              }
            });
          }
        } else {
          // 处理普通对象类型的嵌套字段
          field.fields.forEach((subField: any) => {
            if (
              value.hasOwnProperty(subField.name) &&
              (typeof subField.default === 'undefined' || subField.default === '')
            ) {
              subField.default = value[subField.name];
              console.log(
                `设置嵌套字段默认值: ${field.name}.${subField.name} = ${subField.default}`,
              );
            }
          });
        }
      }

      mergedFields.push(field);
    }
    // 2. fields 里有但 state 没有的补充进来
    for (const f of fields) {
      if (!state.hasOwnProperty(f.name || '')) {
        mergedFields.push(f);

        // 只对没有在 state 中出现的字段进行类型推断
        if (!f.type || f.type === 'string') {
          // 优先根据默认值的格式推断类型
          if (f.default?.startsWith('{')) {
            f.type = 'object';
          } else if (f.default?.startsWith('[')) {
            // 如果是可以转换为数组
            try {
              const arr = JSON.parse(f.default);
              if (Array.isArray(arr)) {
                f.type =
                  typeof arr[0] === 'string'
                    ? 'string'
                    : typeof arr[0] === 'number'
                    ? 'number'
                    : typeof arr[0] === 'boolean'
                    ? 'boolean'
                    : 'object';
                f.isArray = true;
              }
            } catch (e) {
              f.type = 'string';
            }
          } else if (f.default === 'true' || f.default === 'false') {
            // 如果是可以转换为布尔值
            f.type = 'boolean';
          } else if (f.default && /^\d+$/.test(f.default)) {
            // 只有纯数字字符串才转换为 number（避免 '1abc' 这种情况）
            f.type = 'number';
          } else if (f.default && /^\d+\.\d+$/.test(f.default)) {
            // 小数形式的数字
            f.type = 'number';
          } else {
            // 默认为字符串类型
            f.type = 'string';
          }
        }
      }
    }
    dataType.fields = mergedFields;
    dataType = await sampleTypeFromDefault(dataType);
  }

  // 处理 propsType，类似 dataType 的逻辑，使用 defaultProps 补偿默认值
  if (propsType && typeof propsType === 'object' && propsType.name) {
    propsType.type = 'props';
    propsType.desc = propsType.desc || 'props';
    propsType.name = 'props';
    propsType.fileName = fileName;

    // 新逻辑：以 defaultProps 为主合并 fields
    const defaultPropsData = defaultProps || {};
    console.log('defaultProps: ', JSON.parse(JSON.stringify(defaultPropsData)));
    const propsFields = propsType.fields || [];
    const propsFieldsMap = new Map(propsFields.map((f: any) => [f.name, f]));
    const mergedPropsFields: any[] = [];

    // 1. 遍历 defaultProps，优先用 defaultProps 的值
    for (const [name, value] of Object.entries(defaultPropsData)) {
      let field = propsFieldsMap.get(name) || { name };

      // 如果 propsType 中没有默认值，但 defaultProps 中有值，使用 defaultProps 的值作为默认值
      // 但保持 propsType 中已定义的类型
      if (typeof field.default === 'undefined' || field.default === '') {
        field.default = value;

        // 只有当 propsType 中没有明确类型定义时，才根据 defaultProps 值推断类型
        if (!field.type) {
          if (typeof value === 'string') {
            field.type = 'string';
          } else if (typeof value === 'number') {
            field.type = 'number';
          } else if (typeof value === 'boolean') {
            field.type = 'boolean';
          } else if (Array.isArray(value)) {
            field.type =
              typeof value[0] === 'string'
                ? 'string'
                : typeof value[0] === 'number'
                ? 'number'
                : 'object';
            field.isArray = true;
            field.default = JSON.stringify(value, undefined, 2);
          } else if (typeof value === 'object' && value !== null) {
            field.type = 'object';
            field.default = JSON.stringify(value, undefined, 2);
          }
        } else {
          // 如果 propsType 中已有类型定义，需要根据类型格式化默认值
          if (field.type === 'object' && typeof value === 'object' && value !== null) {
            field.default = JSON.stringify(value, undefined, 2);
          } else if (field.isArray && Array.isArray(value)) {
            field.default = JSON.stringify(value, undefined, 2);
          }
          // 其他情况保持原值
        }
      }

      mergedPropsFields.push(field);
    }

    // 2. propsFields 里有但 defaultProps 没有的补充进来
    for (const f of propsFields) {
      if (!defaultPropsData.hasOwnProperty(f.name || '')) {
        mergedPropsFields.push(f);

        // 只对没有在 defaultProps 中出现的字段进行类型推断
        if (!f.type || f.type === 'string') {
          // 优先根据默认值的格式推断类型
          if (f.default?.startsWith('{')) {
            f.type = 'object';
          } else if (f.default?.startsWith('[')) {
            // 如果是可以转换为数组
            try {
              const arr = JSON.parse(f.default);
              if (Array.isArray(arr)) {
                f.type =
                  typeof arr[0] === 'string'
                    ? 'string'
                    : typeof arr[0] === 'number'
                    ? 'number'
                    : typeof arr[0] === 'boolean'
                    ? 'boolean'
                    : 'object';
                f.isArray = true;
              }
            } catch (e) {
              f.type = 'string';
            }
          } else if (f.default === 'true' || f.default === 'false') {
            // 如果是可以转换为布尔值
            f.type = 'boolean';
          } else if (f.default && /^\d+$/.test(f.default)) {
            // 只有纯数字字符串才转换为 number（避免 '1abc' 这种情况）
            f.type = 'number';
          } else if (f.default && /^\d+\.\d+$/.test(f.default)) {
            // 小数形式的数字
            f.type = 'number';
          } else {
            // 默认为字符串类型
            f.type = 'string';
          }
        }
      }
    }

    propsType.fields = mergedPropsFields;
    propsType = await sampleTypeFromDefault(propsType);
  }

  // 添加类型到 newTypes
  if (dataType && typeof dataType === 'object' && dataType.name) {
    newTypes.push(dataType);
  }
  if (propsType && typeof propsType === 'object' && propsType.name) {
    let haveStyleProps = false;
    let haveClassNameProps = false;
    for (const field of propsType.fields || []) {
      if (field.name === 'style') {
        haveStyleProps = true;
      }
      if (field.name === 'className') {
        haveClassNameProps = true;
      }
      // 只有当字段没有通过 @Form 装饰器明确设置 setter 时，才根据类型自动设置
      if (!field.setter) {
        switch (field.type) {
          case 'function':
            field.setter = 'FunctionSetter';
            // 只有当没有明确设置 setterProps 时，才设置默认模板
            if (!field.setterProps) {
              field.setterProps = {
                template: `${field.name}(e){}`,
              };
            }
            break;
          case 'string':
            field.setter = 'StringSetter';
            break;
          case 'number':
            field.setter = 'NumberSetter';
            break;
          case 'boolean':
            field.setter = 'BoolSetter';
            break;
          case 'object':
            field.setter = 'JsonSetter';
            break;
          case 'Date':
            field.setter = 'DatePicker';
            break;
        }
      }

      // 对于函数类型，确保有正确的 setterProps 格式（保持为对象，不要序列化）
      if (field.type === 'function' && field.setter === 'FunctionSetter') {
        // 如果没有 setterProps 或者没有 template，生成默认的
        if (!field.setterProps || !field.setterProps.template) {
          if (!field.setterProps) {
            field.setterProps = {};
          }
          // 生成默认的函数模板
          field.setterProps.template = `${field.name}(e){}`;
        }
      }
    }
    doc.componentMeta = {
      ...(doc.componentMeta || {}),
      configure: {
        ...(doc.componentMeta?.configure || {}),
        props: (propsType.fields || []) as unknown as IPublicTypeFieldConfig[],
        supports: {
          ...((doc.componentMeta?.configure as IPublicTypeConfigure)?.supports || {}),
          style: haveStyleProps,
          className: haveClassNameProps,
        },
      },
      componentName: doc.fileName,
      fileName: doc.fileName,
      title: doc.title,
    };

    propsType.fields = (propsType.fields || []).filter(
      (field) => field.name !== 'style' && field.name !== 'className',
    );
  }
  for (const method of methods) {
    const existType = doc.types?.find((_) => _.name === method.name) || {
      type: 'action',
      fileName,
      name: method.name,
      desc: method.desc,
      language: 'javascript',
      fkId: doc._id,
      projectId: doc.projectId,
    };
    let compiledCode: string | undefined = '';
    // 判断method.code 中是否存在jsx
    if (method.code.match(/<[a-zA-Z][^>]*>/)) {
      compiledCode = transformJS(method.code, defaultBabelConfig).code;
    }
    newTypes.push({
      ...existType,
      name: method.name,
      desc: method.desc,
      code: {
        type: 'JSFunction',
        value: compiledCode || method.code,
      },
      source: method.code,
    });
  }
  // console.log('dataType: ', dataType);
  // console.log('newTypes: ', newTypes);
  // console.log('schema: ', schema);
  // console.log('rootSchema: ', {
  //   ...rootSchema,
  //   ...schema,
  // });
  let updatedSchema: IPublicTypeRootSchema | IPublicTypeProjectSchema = {
    ...rootSchema,
    ...(schema as unknown as IPublicTypeRootSchema),
  };
  if (dataType) {
    updatedSchema = (await dataTypeToSchema(
      null,
      updatedSchema,
      dataType,
      false,
    )) as IPublicTypeRootSchema;
  }
  const actionType = newTypes.find((_) => _.type === 'action');
  if (actionType) {
    updatedSchema = (await actionTypeToSchema(
      null,
      updatedSchema,
      actionType,
      false,
      newTypes,
    )) as IPublicTypeRootSchema;
  }

  if (!updatedSchema.fileName) {
    updatedSchema.fileName = fileName;
  }

  doc.schema = updatedSchema;
  doc.types = newTypes;

  return {
    doc,
  };
};
